home *** CD-ROM | disk | FTP | other *** search
- //////////
- //
- // File: QTSprites.c
- //
- // Contains: QuickTime sprites support for QuickTime movies.
- //
- // Written by: ???
- // Revised by: Deeje Cooley and Tim Monroe
- // Based (heavily!) on the existing MakeSpriteMovie.c code written by ???.
- //
- // Copyright: © 1997-1998 by Apple Computer, Inc., all rights reserved.
- //
- // Change History (most recent first):
- //
- // <4> 09/30/98 rtm tweaked call to AddMovieResource to create single-fork movies
- // <3> 06/19/98 rtm moved to new routine names (e.g. SpriteMediaSetSpriteProperty)
- // <2> 04/09/98 rtm added sprite hit-testing
- // <1> 04/02/98 rtm first file; integrated existing code with shell framework
- //
- // This sample code creates a sprite movie containing one sprite track. The sprite track contains
- // a static background picture sprite (or just a colored background, depending on the value of the
- // global variable gUseBackgroundPicture) and three other sprites that change their properties over time.
- // The track's media contains only one key frame sample followed by many override samples. The key
- // frame contains all of the images used by the sprites; the override frames only contain the overrides
- // of the locations, image indices, and layers needed for the other sprites.
- //
- // This sample code also shows how to hit test sprites. It uses the function SpriteMediaHitTestAllSprites
- // to find mouse clicks on the sprites in the first sprite track in a movie. If the user clicks on a
- // sprite, we toggle the visibility state of the sprite. You would probably want to do something a bit
- // more interesting when the user clicks on a sprite.
- //
- //////////
-
-
- // header files
- #include "QTSprites.h"
-
- // global variables
- Boolean gUseBackgroundPicture = true; // do we display a background picture?
-
-
- ApplicationDataHdl QTSprites_InitWindowData (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData = NULL;
- Track myTrack = NULL;
- MediaHandler myHandler = NULL;
-
- myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord));
- if (myAppData != NULL) {
-
- myTrack = GetMovieIndTrackType((**theWindowObject).fMovie, 1, SpriteMediaType, movieTrackMediaType | movieTrackEnabledOnly);
- if (myTrack != NULL)
- myHandler = GetMediaHandler(GetTrackMedia(myTrack));
-
- // remember the sprite media handler
- (**myAppData).fMovieHasSprites = (myTrack != NULL);
- (**myAppData).fSpriteHandler = myHandler;
- }
-
- return(myAppData);
- }
-
-
- //////////
- //
- // QTSprites_DumpWindowData
- // Get rid of any window-specific data for the sprite media handler.
- //
- //////////
-
- void QTSprites_DumpWindowData (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData = NULL;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData != NULL)
- DisposeHandle((Handle)myAppData);
- }
-
-
- //////////
- //
- // QTSprites_CreateSpritesMovie
- // Create a QuickTime movie containing a sprite track.
- //
- //////////
-
- OSErr QTSprites_CreateSpritesMovie (void)
- {
- short myResRefNum = 0;
- short myResID = movieInDataForkResID;
- Movie myMovie = NULL;
- Track myTrack;
- Media myMedia;
- StandardFileReply myReply;
- QTAtomContainer mySample = NULL;
- QTAtomContainer mySpriteData = NULL;
- RGBColor myKeyColor;
- Point myLocation, myIconLocation;
- short isVisible, myLayer, myIndex, i, myDelta, myIconMinH, myIconMaxH;
- long myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
- OSErr myErr = noErr;
-
- //////////
- //
- // create a new movie file
- //
- //////////
-
- // ask the user for the name of the new movie file
- StandardPutFile("\pSprite movie file name:", "\pSprite.mov", &myReply);
- if (!myReply.sfGood)
- goto bail;
-
- // create a movie file for the destination movie
- myErr = CreateMovieFile(&myReply.sfFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, &myResRefNum, &myMovie);
- if (myErr != noErr)
- goto bail;
-
- //////////
- //
- // create the sprite track and media
- //
- //////////
-
- myTrack = NewMovieTrack(myMovie, ((long)kSpriteTrackWidth << 16), ((long)kSpriteTrackHeight << 16), kNoVolume);
- myMedia = NewTrackMedia(myTrack, SpriteMediaType, kSpriteMediaTimeScale, NULL, 0);
-
- //////////
- //
- // create a key frame sample containing the sprites and all of their shared images
- //
- //////////
-
- // create a new, empty key frame sample
- myErr = QTNewAtomContainer(&mySample);
- if (myErr != noErr)
- goto bail;
-
- myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff; // white
-
- // add images to the key frame sample
- AddPICTImageToKeyFrameSample(mySample, kIconPictID, &myKeyColor, kIconImageIndex, NULL, NULL);
- AddPICTImageToKeyFrameSample(mySample, kWorldPictID, &myKeyColor, kWorldImageIndex, NULL, NULL);
- AddPICTImageToKeyFrameSample(mySample, kBackgroundPictID, &myKeyColor, kBackgroundImageIndex, NULL, NULL);
- for (myIndex = 1; myIndex <= kNumSpaceShipImages; myIndex++)
- AddPICTImageToKeyFrameSample(mySample, kFirstSpaceShipPictID + myIndex - 1, &myKeyColor, myIndex + 3, NULL, NULL);
-
- //////////
- //
- // add samples to the sprite track's media
- //
- //////////
-
- BeginMediaEdits(myMedia);
-
- myErr = QTNewAtomContainer(&mySpriteData);
- if (myErr != noErr)
- goto bail;
-
- // the background image
- if (gUseBackgroundPicture) {
- myLocation.h = 0;
- myLocation.v = 0;
- isVisible = true;
- myLayer = kBackgroundSpriteLayerNum; // this makes the sprite a background sprite
- myIndex = kBackgroundImageIndex;
- myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
- if (myErr != noErr)
- goto bail;
- AddSpriteToSample(mySample, mySpriteData, kBackgroundSpriteAtomID);
- }
-
- // the space ship sprite
- myLocation.h = 0;
- myLocation.v = 60;
- isVisible = true;
- myLayer = -1;
- myIndex = kFirstSpaceShipImageIndex;
- myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
- if (myErr != noErr)
- goto bail;
- AddSpriteToSample(mySample, mySpriteData, kSpaceShipSpriteAtomID);
-
- // the world sprite
- myLocation.h = (kSpriteTrackWidth / 2) - 24;
- myLocation.v = (kSpriteTrackHeight / 2) - 24;
- isVisible = true;
- myLayer = 1;
- myIndex = kWorldImageIndex;
- myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
- if (myErr != noErr)
- goto bail;
- AddSpriteToSample(mySample, mySpriteData, kWorldSpriteAtomID);
-
- // the icon sprite
- myIconMinH = (kSpriteTrackWidth / 2) - 116;
- myIconMaxH = myIconMinH + 200;
- myDelta = 2;
- myIconLocation.h = myIconMinH;
- myIconLocation.v = (kSpriteTrackHeight / 2) - (24 + 12);
- isVisible = true;
- myLayer = 0;
- myIndex = kIconImageIndex;
- myErr = SetSpriteData(mySpriteData, &myIconLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
- if (myErr != noErr)
- goto bail;
- AddSpriteToSample(mySample, mySpriteData, kIconSpriteAtomID);
-
- // add the key frame sample to the sprite track media
- //
- // to add the sample data in a compressed form, you would use a QuickTime DataCodec to perform the
- // compression; replace the call to the utility AddSpriteSampleToMedia with a call to the utility
- // AddCompressedSpriteSampleToMedia to do this
-
- AddSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, true, NULL);
- //AddCompressedSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, true, zlibDataCompressorSubType, NULL);
-
- //////////
- //
- // add a few override samples to move the space ship and icon, and to change the icon's layer
- //
- //////////
-
- // original space ship location
- myIndex = kFirstSpaceShipImageIndex;
- myLocation.h = 0;
- myLocation.v = 80;
- isVisible = true;
-
- for (i = 1; i <= kNumOverrideSamples; i++) {
- QTRemoveChildren(mySample, kParentAtomIsContainer);
- QTRemoveChildren(mySpriteData, kParentAtomIsContainer);
-
- // every third frame, bump the space ship's image index (so that it spins as it moves)
- if ((i % 3) == 0) {
- myIndex++;
- if (myIndex > kLastSpaceShipImageIndex)
- myIndex = kFirstSpaceShipImageIndex;
- }
-
- // every frame, bump the space ship's location (so that it moves as it spins)
- myLocation.h += 2;
- myLocation.v += 1;
-
- if (isVisible)
- SetSpriteData(mySpriteData, &myLocation, NULL, NULL, &myIndex, NULL, NULL, NULL);
- else {
- isVisible = true;
- SetSpriteData(mySpriteData, &myLocation, &isVisible, NULL, &myIndex, NULL, NULL, NULL);
- }
-
- AddSpriteToSample(mySample, mySpriteData, 2);
-
- // make the icon move and change layer
- QTRemoveChildren(mySpriteData, kParentAtomIsContainer);
- myIconLocation.h += myDelta;
-
- if (myIconLocation.h >= myIconMaxH ) {
- myIconLocation.h = myIconMaxH;
- myDelta = -myDelta;
- }
-
- if (myIconLocation.h <= myIconMinH ) {
- myIconLocation.h = myIconMinH;
- myDelta = -myDelta;
- }
-
- if (myDelta > 0)
- myLayer = 0;
- else
- myLayer = 3;
-
- SetSpriteData(mySpriteData, &myIconLocation, NULL, &myLayer, NULL, NULL, NULL, NULL);
- AddSpriteToSample(mySample, mySpriteData, 4);
-
- AddSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, false, NULL);
- }
-
- EndMediaEdits(myMedia);
-
- // add the media to the track
- InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
-
- //////////
- //
- // set the sprite track properties
- //
- //////////
-
- if (!gUseBackgroundPicture) {
- QTAtomContainer myTrackProperties;
- RGBColor myBackgroundColor;
-
- // add a background color to the sprite track
- myBackgroundColor.red = EndianU16_NtoB(0x8000);
- myBackgroundColor.green = EndianU16_NtoB(0);
- myBackgroundColor.blue = EndianU16_NtoB(0xffff);
-
- QTNewAtomContainer(&myTrackProperties);
- QTInsertChild(myTrackProperties, 0, kSpriteTrackPropertyBackgroundColor, 1, 1, sizeof(RGBColor), &myBackgroundColor, NULL);
-
- myErr = SetMediaPropertyAtom(myMedia, myTrackProperties);
- if (myErr != noErr)
- goto bail;
-
- QTDisposeAtomContainer(myTrackProperties);
- }
-
- //////////
- //
- // finish up
- //
- //////////
-
- // add the movie resource to the movie file
- myErr = AddMovieResource(myMovie, myResRefNum, &myResID, myReply.sfFile.name);
-
- bail:
- if (mySample != NULL)
- QTDisposeAtomContainer(mySample);
-
- if (mySpriteData != NULL)
- QTDisposeAtomContainer(mySpriteData);
-
- if (myResRefNum != 0)
- CloseMovieFile(myResRefNum);
-
- if (myMovie != NULL)
- DisposeMovie(myMovie);
-
- return(myErr);
- }
-
-
- //////////
- //
- // QTSprites_HitTestSprites
- // Determine whether a mouse click is on a sprite; return true if it is, false otherwise.
- //
- // This routine is intended to be called from your movie controller action filter function,
- // in response to mcActionMouseDown actions.
- //
- //////////
-
- Boolean QTSprites_HitTestSprites (WindowObject theWindowObject, EventRecord *theEvent)
- {
- ApplicationDataHdl myAppData = NULL;
- MediaHandler myHandler = NULL;
- Boolean isHandled = false;
- long myFlags = 0L;
- QTAtomID myAtomID = 0;
- Point myPoint;
- ComponentResult myErr = noErr;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- goto bail;
-
- if (theEvent == NULL)
- goto bail;
-
- myHandler = (**myAppData).fSpriteHandler;
- myFlags = spriteHitTestImage | spriteHitTestLocInDisplayCoordinates | spriteHitTestInvisibleSprites;
- myPoint = theEvent->where;
-
- myErr = SpriteMediaHitTestAllSprites(myHandler, myFlags, myPoint, &myAtomID);
- if ((myErr == noErr) && (myAtomID != 0)) {
- Boolean isVisible;
-
- // the user has clicked on a sprite;
- // for now, we'll just toggle the visibility state of the sprite
- SpriteMediaGetSpriteProperty(myHandler, myAtomID, kSpritePropertyVisible, (void *)&isVisible);
- SpriteMediaSetSpriteProperty(myHandler, myAtomID, kSpritePropertyVisible, (void *)!isVisible);
-
- isHandled = true;
- }
-
- bail:
- return(isHandled);
- }